#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

struct		Task
{
	char	name[64];
	char	dir[256];
	char	rule[64];
	int		timeout;
	Task	*next;
};

int			run_child(char *outputdir, char *rule)
{
	int		fdout;
	int		fderr;
	char	outname[256];
	char	errname[256];
	char	*argv[3];

	setenv("OUTPUTDIR", outputdir, 1);
	strcpy(outname, outputdir);
	strcat(outname, "/stdout.txt");
	strcpy(errname, outputdir);
	strcat(errname, "/stderr.txt");
	if ((fdout = open(outname, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0)
	{
		perror("open() error");
		return (0);
	}
	if ((fderr = open(errname, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0)
	{
		perror("open() error");
		close(fdout);
		return (0);
	}
	if (dup2(fdout, 1) < 0 || dup2(fderr, 2) < 0)
	{
		perror("dup2() error");
		close(fdout);
		close(fderr);
		return (0);
	}
	argv[0] = "make";
	argv[1] = rule;
	argv[2] = 0;
	if (execvp("make", argv) < 0)
	{
		perror("execvp() error");
		return (0);
	}
	return (1);
}

int			write_end_status(char *outputdir, int status)
{
	int		fd;
	char	filename[256];
	char	str[256];
	
	strcpy(filename, outputdir);
	strcat(filename, "/end_status.txt");
	if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0)
	{
		perror("open() error");
		return (0);
	}
	if (WIFEXITED(status))
		sprintf(str, "exited\n%d\n", WEXITSTATUS(status));
	else if (WIFSIGNALED(status))
		sprintf(str, "signaled\n%d\n", WTERMSIG(status));
	write(fd, str, strlen(str));
	close(fd);
	return (1);
}

int			write_timeout(char *outputdir, int timeout)
{
	int		fd;
	char	filename[256];
	char	str[256];
	
	strcpy(filename, outputdir);
	strcat(filename, "/timeout.txt");
	if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0)
	{
		perror("open() error");
		return (0);
	}
	sprintf(str, "%d\n", timeout);
	write(fd, str, strlen(str));
	close(fd);
	return (1);
}

int			run_supervisor(char *name, char *dir, char *rule, int timeout)
{
	pid_t   childpid;
	pid_t   timerpid;
	time_t	currenttime;
	char	outputdir[256];
	char	strtime[32];
	int		status;
	
	currenttime = time(0);
	strftime(strtime, 32, "%Y-%m-%d_%H-%M-%S", localtime(&currenttime));
	strcpy(outputdir, name);
	strcat(outputdir, strtime);
	if (mkdir(outputdir, 0777) < 0)
	{
		perror("mkdir() error");
		return (0);
	}
	if ((childpid = fork()) > 0)
	{
		if (timeout > 0)
		{
			if ((timerpid = fork()) > 0)
			{
				waitpid(childpid, &status, 0);
				kill(timerpid, SIGSTOP);
				write_end_status(outputdir, status);
			}
			else if (timerpid == 0)
			{
				sleep(timeout);
				kill(childpid, SIGKILL);
				write_timeout(outputdir, timeout);
				exit(EXIT_SUCCESS);
			}
			else
			{
				perror("fork() error");
				//return (0);
			}
		}
	}
	else if (childpid == 0)
		return (run_child(outputdir, rule));
	else
	{
		perror("fork() error");
		return (0);
	}
	return (1);
}

int		read_word(char *str, int *ptr)
{

}

int		read_line(int fd, char *str)
{
	int i;

	for (i = 0; read(fd, str + i, 1); ++i)
	{
		if (str[i] == '\n' || str[i] == '\r')
		{
			str[i] = '\0';
			printf("rl %d\n", i);
			return (i + 1);
		}
	}
	printf("rl %d\n", i);
	return (i);
}


Task	*read_file(char const *filename)
{
	int		fd;
	char	str[256];
	Task	*begin;
		int		i;
	int		j;

	if ((fd = open(av[1], O_RDONLY)) < 0)
	{
		perror("open() errror");
		return (EXIT_FAILURE);
	}
	while (read_line(fd, str))
	{
		current = malloc(sizeof(Task));
		
		if (read_word() && read_word() && read_word() && read_word())
			;
		else
			printf("wrong rule\n");
	}
	close(fd);
}

int 		main(int ac, char **av)
{
	Task	*begin;
	Task	*current;

	if (ac != 2)
	{
		printf("wrong invocation\n");
		return (EXIT_FAILURE);
	}
	if (!(begin = read_file(av[1])))
		return (EXIT_FAILTURE);
	while (running)
	{
		current = begin;
		while (current && running)
		{
			run_supervisor(current->name, current->dir, current->rule, current->timeout);
			current = current->next;
		}
	}
	return (EXIT_SUCCESS);
}
